﻿using System;
using System.Runtime.InteropServices;
using WindowsAPI.Hooks;

namespace WindowsAPI
{
    public static partial class Mouse
    {
        /* --------------------------------------------------------------------------------------------- */

        [Serializable, Flags]
        public enum Message
        {
            MouseMove = 0x0200,
            LeftButtonDown = 0x0201,
            LeftButtonUp = 0x0202,
            RightButtonDown = 0x0204,
            RightButtonUp = 0x0205,
            MiddleButtonDown = 0x207,
            MiddleButtonUp = 0x208,
            MouseWheel = 0x020A
        }

        [Serializable, StructLayout(LayoutKind.Sequential)]
        public struct MsllHookStruct
        {
            public POINT Point;
            public readonly uint MouseData;
            public readonly uint Flags;
            public readonly uint Time;
            public IntPtr dwExtraInfo;

            public override string ToString()
            {
                return string.Format("{0}[{1}|{2}|{3}|{4}]", Point, MouseData, Flags, TimeSpan.FromMilliseconds(Time), dwExtraInfo);
            }

            public static explicit operator MsllHookStruct(IntPtr Pointer)
            {
                return (MsllHookStruct)Marshal.PtrToStructure(Pointer, typeof(MsllHookStruct));
            }
        }

        /* --------------------------------------------------------------------------------------------- */

        //public abstract class MouseEventArgs : EventArgs
        //{
        //    public Message Msg { get; private set; }
        //    public MsllHookStruct Args { get; private set; }

        //    protected MouseEventArgs(Message msg, MsllHookStruct args) { Msg = msg; Args = args; }
        //}

        private static event EventHandler<MouseHookEventArgs> se_MouseEventHandlers;
        public static event EventHandler<MouseHookEventArgs> Events
        {
            add
            {
                var lv_Empty = se_MouseEventHandlers == null;
                se_MouseEventHandlers += value;
                if(lv_Empty) SetHook();
            }
            remove
            {
                se_MouseEventHandlers -= value;
                if(se_MouseEventHandlers == null) ResetHook();
            }
        }

        /* --------------------------------------------------------------------------------------------- */

        private static readonly MouseHookLL sf_MouseHook = new MouseHookLL();

        static Mouse()
        {
            sf_MouseHook.Event += (s, e) =>
                                      {
                                          var handlers = se_MouseEventHandlers;
                                          if(handlers != null)
                                              handlers(s, (MouseHookEventArgs)e);
                                      };
        }

        /* --------------------------------------------------------------------------------------------- */

        public static void SetHook() { sf_MouseHook.Enable = true; }

        public static void ResetHook() { sf_MouseHook.Enable = false; }

        /* --------------------------------------------------------------------------------------------- */
    }
}
